package com.vegetable.modules.service.stock.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vegetable.modules.entity.stock.CostWeightChangeSource;
import com.vegetable.modules.entity.stock.Stock;
import com.vegetable.modules.entity.stock.dto.OrderCostChangeDTO;
import com.vegetable.modules.entity.stock.to.CostWeightChangeQueryTO;
import com.vegetable.modules.mapper.stock.CostWeightChangeSourceMapper;
import com.vegetable.modules.service.stock.ICostWeightChangeQueryService;
import com.vegetable.modules.service.stock.IStockService;
import com.vegetable.modules.vo.CostWeightChangeGroupVO;
import com.vegetable.modules.vo.CostWeightChangeGroupVO.OrderCostChangeDetail;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 成本单价变化查询服务实现类
 * </p>
 *
 * @author wangruijie
 * @since 2024-03-21
 */
@Slf4j
@Service
public class CostWeightChangeQueryServiceImpl extends ServiceImpl<CostWeightChangeSourceMapper, CostWeightChangeSource> implements ICostWeightChangeQueryService {

    @Resource
    private IStockService stockService;

    @Override
    public IPage<CostWeightChangeSource> queryCostWeightChanges(CostWeightChangeQueryTO queryTO) {
        QueryWrapper<CostWeightChangeSource> queryWrapper = new QueryWrapper<>();
        
        // 根据商品ID查询
        if (queryTO.getCommodityId() != null) {
            queryWrapper.eq("commodity_id", queryTO.getCommodityId());
        }
        
        // 根据商品名称模糊查询
        if (StringUtils.hasText(queryTO.getCommodityName())) {
            queryWrapper.like("commodity_name", queryTO.getCommodityName());
        }
        
        // 根据库存ID查询
        if (queryTO.getStockId() != null) {
            queryWrapper.eq("stock_id", queryTO.getStockId());
        }
        
        // 根据变化源头类型查询
        if (queryTO.getSourceType() != null) {
            queryWrapper.eq("source_type", queryTO.getSourceType());
        }
        
        // 根据操作人查询
        if (StringUtils.hasText(queryTO.getOperatorName())) {
            queryWrapper.like("operator_name", queryTO.getOperatorName());
        }
        
        // 根据操作时间范围查询
        if (queryTO.getStartTime() != null) {
            queryWrapper.ge("operate_time", queryTO.getStartTime());
        }
        
        if (queryTO.getEndTime() != null) {
            queryWrapper.le("operate_time", queryTO.getEndTime());
        }
        
        // 根据变化差值范围查询
        if (queryTO.getMinChangeAmount() != null) {
            queryWrapper.ge("change_amount", queryTO.getMinChangeAmount());
        }
        
        if (queryTO.getMaxChangeAmount() != null) {
            queryWrapper.le("change_amount", queryTO.getMaxChangeAmount());
        }
        
        // 根据源头订单ID查询
        if (queryTO.getSourceOrderId() != null) {
            queryWrapper.eq("source_order_id", queryTO.getSourceOrderId());
        }
        
        // 只查询连锁变化
        if (Boolean.TRUE.equals(queryTO.getChainChangesOnly())) {
            queryWrapper.eq("source_type", 4); // 重新包装（连锁反应）
        }
        
        // 根据变化方向查询
        if (queryTO.getChangeDirection() != null) {
            switch (queryTO.getChangeDirection()) {
                case 1: // 增加
                    queryWrapper.gt("change_amount", BigDecimal.ZERO);
                    break;
                case -1: // 减少
                    queryWrapper.lt("change_amount", BigDecimal.ZERO);
                    break;
                case 0: // 无变化
                    queryWrapper.eq("change_amount", BigDecimal.ZERO);
                    break;
            }
        }
        
        // 根据变化百分比范围查询
        if (queryTO.getMinChangePercentage() != null) {
            // 这里需要通过自定义SQL实现，简化处理
        }
        
        if (queryTO.getMaxChangePercentage() != null) {
            // 这里需要通过自定义SQL实现，简化处理
        }
        
        // 按操作时间倒序排列
        queryWrapper.orderByDesc("operate_time");
        
        // 分页查询
        Page<CostWeightChangeSource> page = new Page<>(queryTO.getPage(), queryTO.getLimit());
        return this.page(page, queryWrapper);
    }
    
    /**
     * 分组查询成本单价变化记录
     * @param queryTO 查询条件
     * @return 分组结果
     */
    public IPage<CostWeightChangeGroupVO> queryCostWeightChangesGrouped(CostWeightChangeQueryTO queryTO) {
        // 首先查询原始数据
        IPage<CostWeightChangeSource> rawPage = queryCostWeightChanges(queryTO);
        
        // 将原始数据转换为分组数据
        List<CostWeightChangeGroupVO> groupedData = rawPage.getRecords().stream()
            .collect(Collectors.groupingBy(change -> change.getTtid() != null ? change.getTtid() : "未知链路ID")) // 只按照链路ID分组，处理null值
            .values().stream()
            .map(changes -> {
                // 先按操作时间排序
                List<CostWeightChangeSource> sortedChanges = changes.stream()
                    .sorted(Comparator.comparing(CostWeightChangeSource::getOperateTime))
                    .collect(Collectors.toList());
                
                CostWeightChangeGroupVO groupVO = new CostWeightChangeGroupVO();
                CostWeightChangeSource firstChange = sortedChanges.get(0);
                CostWeightChangeSource lastChange = sortedChanges.get(sortedChanges.size() - 1);
                
                // 设置分组字段（取第一条记录的值）
                groupVO.setTtid(firstChange.getTtid() != null ? firstChange.getTtid() : "未知链路ID");
                groupVO.setCommodityId(firstChange.getCommodityId());
                groupVO.setCommodityName(firstChange.getCommodityName());
                groupVO.setSpecsId(firstChange.getSpecsId());
                groupVO.setSpecsName(firstChange.getSpecsName());
                groupVO.setStockBatchNo(firstChange.getStockBatchNo());
                
                // 计算变化前后成本单价（取第一条记录的beforeCostWeight和最后一条记录的afterCostWeight）
                groupVO.setBeforeCostWeight(firstChange.getBeforeCostWeight());
                groupVO.setAfterCostWeight(lastChange.getAfterCostWeight());
                
                // 正确计算变化差值：使用最后的afterCostWeight减去最初的beforeCostWeight
                if (groupVO.getBeforeCostWeight() != null && groupVO.getAfterCostWeight() != null) {
                    groupVO.setChangeAmount(groupVO.getAfterCostWeight().subtract(groupVO.getBeforeCostWeight()));
                } else {
                    groupVO.setChangeAmount(BigDecimal.ZERO);
                }
                
                // 计算变化幅度百分比
                if (groupVO.getBeforeCostWeight() != null && 
                    groupVO.getBeforeCostWeight().compareTo(BigDecimal.ZERO) != 0) {
                    BigDecimal percentage = groupVO.getChangeAmount().multiply(new BigDecimal("100"))
                        .divide(groupVO.getBeforeCostWeight(), 2, BigDecimal.ROUND_HALF_UP);
                    groupVO.setChangePercentage(percentage.toString() + "%");
                } else {
                    groupVO.setChangePercentage("0%");
                }
                
                // 获取首次和最后变化时间
                groupVO.setFirstChangeTime(sortedChanges.stream()
                    .map(CostWeightChangeSource::getOperateTime)
                    .min(Date::compareTo)
                    .orElse(null));
                groupVO.setLastChangeTime(sortedChanges.stream()
                    .map(CostWeightChangeSource::getOperateTime)
                    .max(Date::compareTo)
                    .orElse(null));
                
                // 设置变化记录总数
                groupVO.setChangeCount(sortedChanges.size());
                
                // 设置操作人姓名列表（去重）
                groupVO.setOperatorNames(sortedChanges.stream()
                    .map(CostWeightChangeSource::getOperatorName)
                    .distinct()
                    .collect(Collectors.toList()));
                
                // 设置变化类型描述列表（去重）
                groupVO.setSourceTypeDescriptions(sortedChanges.stream()
                    .map(CostWeightChangeSource::getSourceTypeDescription)
                    .distinct()
                    .collect(Collectors.toList()));
                
                // 设置详细变化记录列表
                groupVO.setDetailChanges(sortedChanges);
                
                // 设置订单费用变化详情列表
                List<OrderCostChangeDetail> orderCostChangeDetails = sortedChanges.stream()
                    .filter(change -> change.getOrderCostChanges() != null && !change.getOrderCostChanges().isEmpty())
                    .map(change -> {
                        try {
                            OrderCostChangeDTO orderCostChangeDTO = com.alibaba.fastjson.JSON.parseObject(
                                change.getOrderCostChanges(), OrderCostChangeDTO.class);
                            if (orderCostChangeDTO != null) {
                                OrderCostChangeDetail detail = new OrderCostChangeDetail();
                                detail.setCostName(orderCostChangeDTO.getCostName());
                                detail.setBeforeCost(orderCostChangeDTO.getBeforeCost());
                                detail.setAfterCost(orderCostChangeDTO.getAfterCost());
                                detail.setCostChange(orderCostChangeDTO.getCostChange());
                                detail.setChangeTime(change.getOperateTime());
                                detail.setOperatorName(change.getOperatorName());
                                return detail;
                            }
                        } catch (Exception e) {
                            log.warn("解析订单费用变化信息时发生错误", e);
                        }
                        return null;
                    })
                    .filter(detail -> detail != null)
                    .collect(Collectors.toList());
                
                groupVO.setOrderCostChangeDetails(orderCostChangeDetails);
                
                return groupVO;
            })
            .collect(Collectors.toList());
        
        // 创建分页结果
        Page<CostWeightChangeGroupVO> resultPage = new Page<>(rawPage.getCurrent(), rawPage.getSize(), rawPage.getTotal());
        resultPage.setRecords(groupedData);
        
        return resultPage;
    }
    
    /**
     * 根据源头订单ID查询连锁变化链路
     * @param sourceOrderId 源头订单ID
     * @return 连锁变化链路列表
     */
    public List<CostWeightChangeSource> queryChainChangesBySourceOrder(Long sourceOrderId) {
        QueryWrapper<CostWeightChangeSource> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("source_order_id", sourceOrderId);
        queryWrapper.orderByAsc("operate_time");
        return this.list(queryWrapper);
    }
    
    /**
     * 根据库存ID查询所有相关变化（包括直接变化和连锁变化）
     * @param stockId 库存ID
     * @return 相关变化列表
     */
    public List<CostWeightChangeSource> queryRelatedChangesByStockId(Long stockId) {
        QueryWrapper<CostWeightChangeSource> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("stock_id", stockId);
        // 获取库存的商品ID
        Stock stock = stockService.selectById(stockId);
        if (stock != null) {
            queryWrapper.or().eq("related_commodity_id", stock.getCommodityId());
        }
        queryWrapper.orderByDesc("operate_time");
        return this.list(queryWrapper);
    }
    
    /**
     * 查询显著成本变化记录
     * @param threshold 阈值
     * @return 显著成本变化记录列表
     */
    public List<CostWeightChangeSource> querySignificantChanges(BigDecimal threshold) {
        QueryWrapper<CostWeightChangeSource> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> wrapper.ge("change_amount", threshold)
            .or()
            .le("change_amount", threshold.negate()));
        queryWrapper.orderByDesc("operate_time");
        return this.list(queryWrapper);
    }
}